<template>
  <div>
    <el-table
      ref="el-table"
      class="el-table"
      :data="list"
      v-bind="_elTable"
      v-on="tableListeners"
    >
      <!-- 支持表格行多选 -->
      <template v-if="_elTable.selectiveType === 'checkbox'">
        <el-table-column type="selection" reserve-selection align="center" />
      </template>
      <!--------------------------------------- 表格内容配置 ------------------------------------------>
      <template v-for="(item, index) in _columns">
        <el-table-column :key="index" v-bind="item">
          <!-- 考虑到对手机、邮箱账号脱敏，在业务场景中需求较为频繁，所以通过encrypt字段对此场景作预定义 -->
          <template v-if="item.encrypt || item.isSlotHeader" #header>
            <!-- 脱敏"眼睛切换按钮" -->
            <span v-if="item.encrypt">
              {{ item.label }}
              <svg-icon
                class="icon"
                style="cursor: pointer"
                :icon-class="desensitization[item.prop] ? 'eye_open' : 'eye_close'"
                @click="desensitization[item.prop] = !desensitization[item.prop]"
              />
            </span>
            <!-- 自定义列表头内容   -->
            <slot v-if="item.isSlotHeader" name="header" :column="item" />
          </template>
          <template v-if="item.encrypt || item.isSlot" #default="{row}">
            <!-- 脱敏内容 -->
            <span v-if="item.encrypt">{{ format(row[item.prop], item.encrypt, item.prop) }}</span>
            <!-- 单元格自定义内容 -->
            <slot v-if="item.isSlot" name="default" :row="row" :column="item" />
          </template>
        </el-table-column>
      </template>
      <!----------------------------------------- 行按钮配置 -------------------------------------------->
      <el-table-column v-if="_elTable.btnsGroup" align="center" label="操作">
        <template slot-scope="scope">
          <template v-for="(item, index) in _calcBtns(scope.row)">
            <!-- 删除按钮 -->
            <el-popconfirm
              v-if="item.type === 'delete'"
              :key="index"
              icon="el-icon-info"
              icon-color="red"
              :title="
                item.deleteTip ? item.deleteTip : '您确定要删除本条数据吗？'
              "
              @confirm="_handleClick(item, scope.row)"
            >
              <el-button
                slot="reference"
                style="margin-left: 10px; color: red"
                type="text"
                size="mini"
              >{{ item.label }}</el-button>
            </el-popconfirm>
            <!-- 常规按钮 -->
            <el-button
              v-else
              :key="index"
              size="mini"
              type="text"
              @click="_handleClick(item, scope.row,$event)"
            >{{ item.label }}</el-button>
          </template>
        </template>
      </el-table-column>
    </el-table>
  </div>

</template>

<script>
export default {
  props: {
    config: {
      type: Object,
      default() {
        return {}
      }
    },
    list: {
      type: Array,
      default() {
        return []
      }
    }
  },
  data() {
    return {
      // 记录脱敏字段状态
      desensitization: {}
    }
  },
  computed: {
    _elTable() {
      const defaultVal = {
        columns: [],
        rowKey: undefined,
        border: true,
        style: 'width: 100%',
        headerRowStyle() {
          return {
            backgroundColor: '#f7f7f7'
          }
        }
      }
      return Object.assign({}, defaultVal, this.config)
    },
    _columns() {
      return this._elTable['columns'].map((col) => {
        if (!col.formatter) {
          col.formatter = (row, col, cell) => {
            return cell === null || cell === undefined || cell === ''
              ? '-'
              : cell
          }
        }
        col.align = col.align || 'left'
        return col
      })
    },
    tableListeners() {
      // eslint-disable-next-line no-unused-vars
      const { tap, ...listeners } = this.$listeners
      return listeners
    }
  },
  watch: {
    config: {
      handler(newVal) {
        const { columns } = newVal
        if (!Array.isArray(columns)) return
        // 对脱敏字段状态进行初始化,默认为true
        columns.forEach((elem) => {
          const { encrypt, prop } = elem
          if (encrypt !== undefined) {
            this.$set(this.desensitization, prop, true)
          }
        })
      },
      immediate: true,
      deep: true
    }
  },
  methods: {
    format(val, encrypt, prop) {
      if (!this.desensitization[prop]) return val
      switch (encrypt) {
        case 'phone':
          // eslint-disable-next-line no-case-declarations
          const regExp = /(\d{3})\d*(\d{4})/
          return val ? val.replace(regExp, '$1****$2') : ''
        case 'email':
          return val
            ? val.substr(0, 2) + '****' + val.substr(val.indexOf('@'))
            : ''
        case 'idCard':
          return this.idCardMask(val)
        case 'username':
          return this.nameMask(val)
        default:
          return val
      }
    },
    idCardMask(idCard, len = 3) {
      if (!idCard) return ''
      const charArr = idCard.split('')
      return charArr
        .map((char, idx) => {
          return idx >= len && idx < idCard.length - len ? '*' : char
        })
        .join('')
    },
    nameMask(name) {
      if (!name) return ''
      const len = name.length
      const symbolFactory = function(length) {
        let result = ''
        for (let i = 0; i < length; i++) {
          result += '*'
        }
        return result
      }
      if (/[\u4e00-\u9fa5]/.test(name)) {
        // 纯中文
        switch (len) {
          case 1:
            // eslint-disable-next-line no-self-assign
            name = name
            break
          case 2:
            name = `${name.charAt(0)}*`
            break
          default:
            name = `${name.charAt(0)}*${name.charAt(len - 1)}`
        }
      } else {
        // 非中文
        if (len > 7) {
          const isEven = len % 2 === 0
          const ceilVal = Math.ceil(len * 0.3)
          if (isEven) {
            // 偶数
            const front = ceilVal
            const middle = len % 3 === 0 ? len / 3 : Math.floor(len / 3) + 1
            const end = front + middle
            name = name.slice(0, front) + symbolFactory(middle) + name.slice(end)
          } else {
            // 奇数
            const front = ceilVal
            const middle = ceilVal
            const end = ceilVal * 2
            name = name.slice(0, front) + symbolFactory(middle) + name.slice(end)
          }
        } else {
          const ceilVal = Math.ceil(len * 0.5)
          name = name.slice(0, ceilVal) + symbolFactory(len - ceilVal)
        }
      }
      return name
    },
    // 行按钮点击事件
    _handleClick(item, row, event) {
      this.$emit('tap', {
        btn: item,
        rowInfo: row,
        event
      })
    },
    // 判断表格行显示内容
    _calcBtns(row) {
      const btnsGroup = this._elTable.btnsGroup
      if (typeof btnsGroup === 'function') {
        return btnsGroup(row) || []
      }
      return btnsGroup
    }
  }
}
</script>
<style lang="scss" scoped>
 .el-table /deep/ .el-table__header th {
    background-color: #f7f7f7;
  }
</style>
